using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UniversalAdmin.Application.Dto;
using Microsoft.AspNetCore.Http;
using UniversalAdmin.Application.Commands;
using UniversalAdmin.Shared.Enums;
using UniversalAdmin.Domain.Repositories;
using UniversalAdmin.Domain.Entities.App;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using Microsoft.AspNetCore.Http.Extensions;
using System.Security.Claims;

namespace UniversalAdmin.Application.Services;

public class AppFileService : IAppFileService
{
    private readonly IRepository<AppFile> _fileRepository;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public AppFileService(IRepository<AppFile> fileRepository, IHttpContextAccessor httpContextAccessor)
    {
        _fileRepository = fileRepository;
        _httpContextAccessor = httpContextAccessor;
    }
    public async Task<ApiResult<PagedResult<FileDto>>> GetPagedAsync(PagedQuery query)
    {
        try
        {
            // 查询未删除的文件
            var queryable = _fileRepository.Table;
            
            // 如果有搜索条件，添加搜索过滤
            if (!string.IsNullOrEmpty(query.Search))
            {
                queryable = queryable.Where(f => f.FileName.Contains(query.Search) || f.OriginalName.Contains(query.Search));
            }
            
            // 获取总数
            var total = await queryable.CountAsync();
            
            // 分页查询
            var files = await queryable
                .OrderByDescending(f => f.CreatedAt)
                .ThenBy(f => f.Id)
                .Skip((query.Page - 1) * query.Size)
                .Take(query.Size)
                .ToListAsync();
            
            // 转换为DTO
            var fileDtos = files.Select(f => new FileDto
            {
                Id = f.Id,
                FileName = f.FileName,
                FilePath = f.Path,
                FileSize = f.Size,
                ContentType = f.MimeType,
                UploadedBy = f.UuId,
                UploadedAt = f.CreatedAt
            }).ToList();
            
            return ApiResult<PagedResult<FileDto>>.Success(
                new PagedResult<FileDto>(fileDtos, total, query.Page, query.Size), 
                "操作成功");
        }
        catch (Exception ex)
        {
            return ApiResult<PagedResult<FileDto>>.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取文件列表时发生错误: {ex.Message}");
        }
    }

    public async Task<ApiResult<IEnumerable<FileDto>>> GetAllAsync(string? search = null)
    {
        try
        {
            // 查询未删除的文件
            var queryable = _fileRepository.Table;
            
            // 如果有搜索条件，添加搜索过滤
            if (!string.IsNullOrEmpty(search))
            {
                queryable = queryable.Where(f => f.FileName.Contains(search) || f.OriginalName.Contains(search));
            }
            
            var files = await queryable
                .OrderByDescending(f => f.CreatedAt)
                .ThenBy(f => f.Id)
                .ToListAsync();
            
            // 转换为DTO
            var fileDtos = files.Select(f => new FileDto
            {
                Id = f.Id,
                FileName = f.FileName,
                FilePath = f.Path,
                FileSize = f.Size,
                ContentType = f.MimeType,
                UploadedBy = f.UuId,
                UploadedAt = f.CreatedAt
            });
            
            return ApiResult<IEnumerable<FileDto>>.Success(fileDtos, "操作成功");
        }
        catch (Exception ex)
        {
            return ApiResult<IEnumerable<FileDto>>.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取文件列表时发生错误: {ex.Message}");
        }
    }
    
    public async Task<ApiResult<FileDto>> GetByIdAsync(Guid id)
    {
        try
        {
            // 查询未删除的文件
            var file = await _fileRepository.Table.FirstOrDefaultAsync(f => f.Id == id);
            
            if (file == null)
            {
                // 检查是否是因为文件不存在还是已删除
                var deletedFile = await _fileRepository.All.FirstOrDefaultAsync(f => f.Id == id && f.IsDelete);
                
                if (deletedFile != null)
                {
                    return ApiResult<FileDto>.Failed((int)ApiStatusCode.NOT_FOUND, "文件已被删除");
                }
                else
                {
                    return ApiResult<FileDto>.Failed((int)ApiStatusCode.NOT_FOUND, "文件不存在");
                }
            }
            
            var fileDto = new FileDto
            {
                Id = file.Id,
                FileName = file.FileName,
                FilePath = file.Path,
                FileSize = file.Size,
                ContentType = file.MimeType,
                UploadedBy = file.UuId,
                UploadedAt = file.CreatedAt
            };
            
            return ApiResult<FileDto>.Success(fileDto, "获取文件成功");
        }
        catch (Exception ex)
        {
            return ApiResult<FileDto>.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取文件时发生错误: {ex.Message}");
        }
    }
    
    public async Task<ApiResult<FileDto>> UploadAsync(IFormFile file)
    {
        try
        {
            if (file == null || file.Length == 0)
            {
                return ApiResult<FileDto>.Failed((int)ApiStatusCode.BAD_REQUEST, "请选择要上传的文件");
            }

            // 文件大小验证（10MB）
            const long maxFileSize = 10 * 1024 * 1024; // 10MB
            if (file.Length > maxFileSize)
            {
                return ApiResult<FileDto>.Failed((int)ApiStatusCode.BAD_REQUEST, $"文件大小不能超过10MB，当前文件大小：{file.Length / 1024 / 1024}MB");
            }

            // 文件类型验证
            var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".txt", ".zip", ".rar" };
            var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
            if (!allowedExtensions.Contains(fileExtension))
            {
                return ApiResult<FileDto>.Failed((int)ApiStatusCode.BAD_REQUEST, $"不支持的文件类型：{fileExtension}，支持的类型：{string.Join(", ", allowedExtensions)}");
            }

            // 获取当前登录用户ID
            var userId = GetCurrentUserId();
            if (userId == Guid.Empty)
            {
                return ApiResult<FileDto>.Failed((int)ApiStatusCode.UNAUTHORIZED, "用户未登录");
            }

            // 保存文件到磁盘
            var (filePath, fileName) = await SaveFileToDisk(file);

            // 创建文件记录
            var appFile = CreateFileRecord(fileName, filePath, file, userId);

            // 保存到数据库
            await _fileRepository.CreatedAsync(appFile);

            // 转换为DTO
            var fileDto = ConvertToFileDto(appFile);

            return ApiResult<FileDto>.Success(fileDto, "文件上传成功");
        }
        catch (Exception ex)
        {
            return ApiResult<FileDto>.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"文件上传失败: {ex.Message}");
        }
    }

    // 获取当前登录用户ID
    private Guid GetCurrentUserId()
    {
        var userIdStr = _httpContextAccessor.HttpContext?.User?.FindFirst("UserId")?.Value;
        return Guid.TryParse(userIdStr, out Guid userId) ? userId : Guid.Empty;
    }

    // 保存文件到磁盘
    private async Task<(string filePath, string fileName)> SaveFileToDisk(IFormFile file)
    {
        var fileName = $"{Guid.NewGuid()}_{file.FileName}";
        var filePath = Path.Combine("uploads", fileName);
        var fullPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", filePath);

        // 确保目录存在
        var directory = Path.GetDirectoryName(fullPath);
        if (!Directory.Exists(directory))
        {
            Directory.CreateDirectory(directory!);
        }

        // 保存文件到磁盘
        using (var stream = new FileStream(fullPath, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }

        return (filePath, fileName);
    }

    // 创建文件记录
    private AppFile CreateFileRecord(string fileName, string filePath, IFormFile file, Guid userId)
    {
        var appFile = new AppFile
        {
            Name = fileName,
            OriginalName = file.FileName,
            Path = filePath,
            Url = $"/{filePath}",
            Size = file.Length,
            MimeType = file.ContentType,
            FileName = file.FileName,
            UuId = userId
        };
        
        // 发布领域事件
        appFile.OnCreated();
        
        return appFile;
    }

    // 转换为FileDto
    private FileDto ConvertToFileDto(AppFile appFile)
    {
        return new FileDto
        {
            Id = appFile.Id,
            FileName = appFile.FileName,
            FilePath = appFile.Path,
            FileSize = appFile.Size,
            ContentType = appFile.MimeType,
            UploadedBy = appFile.UuId,
            UploadedAt = appFile.CreatedAt
        };
    }

    public async Task<ApiResult> DeleteAsync(Guid id)
    {
        try
        {
            // 查询未删除的文件
            var file = await _fileRepository.Table.FirstOrDefaultAsync(f => f.Id == id);
            
            if (file == null)
            {
                // 检查是否是因为文件不存在还是已删除
                var deletedFile = await _fileRepository.All.FirstOrDefaultAsync(f => f.Id == id && f.IsDelete);
                
                if (deletedFile != null)
                {
                    return ApiResult.Success("文件已经被删除");
                }
                else
                {
                    return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "文件不存在");
                }
            }
            
            // 删除物理文件
            var fullPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", file.Path);
            if (System.IO.File.Exists(fullPath))
            {
                System.IO.File.Delete(fullPath);
            }
            
            // 执行软删除（修改数据库删除状态）
            file.MarkAsDeleted();
            await _fileRepository.UpdateAsync(file);
            
            return ApiResult.Success("文件删除成功");
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"删除文件时发生错误: {ex.Message}");
        }
    }
} 